package com.justreading.nio;

import sun.nio.ch.FileChannelImpl;

import java.io.*;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * @author LYJ
 * @Description
 * @date 2021 年 09 月 30 日 下午6:51
 */
public class NIOFileChannel {


    public static void main(String[] args) throws IOException {
//        channelWrite();
//        channelRead();
//        usingOneBufferToFinishCopy();
//        usingTransFromToFinishCopy();
//        useReadOnlyBuffer();
//        useMapByteBuffer();
        useMultiBufferAndServerSocketChannel();
    }


    private static void useMultiBufferAndServerSocketChannel() throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(7777);
        serverSocketChannel.socket().bind(inetSocketAddress);

        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(3);
        System.out.println("启动程序监听中");
        SocketChannel channel = serverSocketChannel.accept();
        int maxLength = 8;
        while (true) {
            int byteRead = 0;
            while (byteRead < maxLength) {
                long read = channel.read(byteBuffers);
                byteRead += read;
                System.out.println("累计从网络中读取的字节数: " + byteRead);
                Arrays.stream(byteBuffers).map(byteBuffer -> "position=" + byteBuffer.position() + ",limit=" + byteBuffer.limit()).forEach(System.out::println);
            }

            //将所有的buffer进行翻转
            Arrays.stream(byteBuffers).forEach(Buffer::flip);

            //输出到客户端
            int byteWrite = 0;
            while (byteWrite < maxLength) {
                long l = channel.write(byteBuffers);
                byteWrite += l;
                System.out.println("累计写到channel中字节数:" + byteWrite);
            }

            Arrays.asList(byteBuffers).forEach(Buffer::clear);

            System.out.println("byteRead:=" + byteRead + " byteWrite=" + byteWrite + ", messagelength" +
                    maxLength);
        }


    }


    private static void useMapByteBuffer() throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile("mapByteBuffer.txt", "rw");
        MappedByteBuffer map = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 7);
        map.put(6, (byte) 'H');

        randomAccessFile.close();
        System.out.println("修改成功");
    }


    //只读buffer
    private static void useReadOnlyBuffer() {
        ByteBuffer byteBuffer = ByteBuffer.allocate(5);
//        byteBuffer.putLong(10L);
//        byteBuffer.putShort((short) 4);
//        byteBuffer.putChar('中');
//        byteBuffer.flip();

        for (int i = 0; i < 5; i++) {
            byteBuffer.put((byte) i);
        }
        byteBuffer.flip();
        ByteBuffer readOnlyBuffer = byteBuffer.asReadOnlyBuffer();
        while (readOnlyBuffer.hasRemaining()) {
            System.out.println(readOnlyBuffer.get());
        }
        readOnlyBuffer.flip();
        readOnlyBuffer.putLong(30);
    }


    private static void usingTransFromToFinishCopy() throws IOException {
        FileInputStream fileInputStream = new FileInputStream("1.txt");
        FileOutputStream fileOutputStream = new FileOutputStream("2.txt");

        FileChannel fileInputStreamChannel = fileInputStream.getChannel();
        FileChannel fileOutputStreamChannel = fileOutputStream.getChannel();

        fileOutputStreamChannel.transferFrom(fileInputStreamChannel, 0, fileInputStreamChannel.size());

        fileInputStream.close();
        fileOutputStream.close();
    }

    private static void usingOneBufferToFinishCopy() throws IOException {
        FileInputStream fileInputStream = new FileInputStream("1.txt");
        FileOutputStream fileOutputStream = new FileOutputStream("2.txt");

        FileChannel fileInputStreamChannel = fileInputStream.getChannel();
        FileChannel fileOutputStreamChannel = fileOutputStream.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        int len;
        while ((len = fileInputStreamChannel.read(byteBuffer)) != -1) {
            byteBuffer.flip();
            fileOutputStreamChannel.write(byteBuffer);
            byteBuffer.clear();
        }
        fileInputStream.close();
        fileOutputStream.close();
    }


    private static void channelRead() throws IOException {
        File file = new File("file.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        FileChannel channel = fileInputStream.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
        channel.read(byteBuffer);
        System.out.println(new String(byteBuffer.array()));
        fileInputStream.close();

    }

    private static void channelWrite() {
        FileOutputStream fos = null;
        FileChannel fileChannel = null;
        try {
            fos = new FileOutputStream("file.txt");
            fileChannel = fos.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            String str = "国庆快乐";
            byteBuffer.put(str.getBytes());
            byteBuffer.flip();
            fileChannel.write(byteBuffer);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (fileChannel != null) {
                try {
                    fileChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
